package com.woniuxy.filter;


import com.woniu.zsd.commons.core.JWTUtil;
import com.woniuxy.content.RedisKey;
import com.woniuxy.config.JwtConfig;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class JwtAuthenticationFilter implements GlobalFilter, Ordered {
    private final JwtConfig jwtConfig;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    public JwtAuthenticationFilter(JwtConfig jwtConfig) {
        this.jwtConfig = jwtConfig;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        // 获取请求路径
//        String path = exchange.getRequest().getPath().toString();
//        // 检查是否在白名单中
//        if (isWhiteList(path)) {
//            return chain.filter(exchange); // 放行白名单路径
//        }
//        // 获取 Authorization 头
//        String token = exchange.getRequest().getHeaders().getFirst("token");
//        System.out.println("token:"+token);
//        if (token == null ) {
//            return unauthorized(exchange, "请提供身份凭证");
//        }
//        // 验证 Token 是否有效
//        if (!JWTUtil.validateToken(token)) {
//            return unauthorized(exchange, "请提供有效的身份凭证");
//        }          // 放行请求
//        //判断redis是否存在该key  不存在准备更新token
//        Boolean b = stringRedisTemplate.hasKey(RedisKey.USER_ACCESS_TOKEN_KEY(token));
//        System.out.println(b);
//        if(!b){
//            //获取用户id
//            String userId = JWTUtil.AnalyzeToken(token).get("id").toString();
//            Map<String,Object> map = new HashMap<>();
//            map.put("id", userId);
//            //更新token
//            String accessToken = JWTUtil.GenerateToken(map,60*60*2);
//            String refreshToken = JWTUtil.GenerateToken(map,60*60*24);
//            stringRedisTemplate.opsForValue().set(RedisKey.USER_REFRESH_TOKEN_KEY(accessToken),refreshToken, 60 * 24, TimeUnit.MINUTES);
//            stringRedisTemplate.opsForValue().set(RedisKey.USER_ACCESS_TOKEN_KEY(String.valueOf(userId)),accessToken, 30, TimeUnit.MINUTES);
//            stringRedisTemplate.opsForValue().set(RedisKey.ACCESS_TIME_OUT(accessToken),String.valueOf( userId), 30, TimeUnit.MINUTES);
//            //更新响应头
//            exchange.getResponse().getHeaders().add("token",accessToken);
//        }
        return chain.filter(exchange);
    }

    /** @description: 检查路径是否在白名单中      * @params: [path]      * @return: boolean */
    private boolean isWhiteList(String path) {
        Map<String, List<String>> whiteLists = jwtConfig.getWhiteList();
        for (Map.Entry<String, List<String>> entry : whiteLists.entrySet()) {
            for (String pattern : entry.getValue()) {
                if (pattern.contains("**")) {
                    // 匹配通配符路径
                    String regex = pattern.replace("**", ".*");
                    if (path.matches(regex)) {
                        return true;
                    }
                } else {
                    // 精确匹配
                    if (path.equals(pattern)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /** @description: 未认证返回
     * * @params: [exchange, msg]
     * * @return: reactor.core.publisher.Mono<java.lang.Void>
     *   */
    private Mono<Void> unauthorized(ServerWebExchange exchange, String msg) {
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(msg.getBytes(StandardCharsets.UTF_8))));
    }

    @Override
    public int getOrder() {
        return -100; // 设置过滤器优先级
    }
}

